package com.rs.game.player;

import java.io.Serializable;

import com.rs.cache.loaders.ItemDefinitions;
import com.rs.game.item.Item;
import com.rs.game.player.skills.Combat;
import com.rs.utils.ItemBonuses;

public final class CombatDefinitions implements Serializable {

	private static final long serialVersionUID = 2102201264836121104L;
	public static final int STAB_ATTACK = 0, SLASH_ATTACK = 1, CRUSH_ATTACK = 2, RANGE_ATTACK = 4, MAGIC_ATTACK = 3;
	public static final int STAB_DEF = 5, SLASH_DEF = 6, CRUSH_DEF = 7, RANGE_DEF = 9, MAGIC_DEF = 8;
	public static final int STRENGTH_BONUS = 14, RANGED_STR_BONUS = 15, MAGIC_DAMAGE = 17;
	public static final int ABSORVE_MELEE_BONUS = 11, ABSORVE_RANGE_BONUS = 12, ABSORVE_MAGE_BONUS = 13;
	
	public static final int SHARED = -1;
	private transient Player player;
	private transient boolean usingSpecialAttack;
	private transient int[] bonuses;
	
	
	//saving stuff

	private byte attackStyle;
	private byte specialAttackPercentage;
	private boolean autoRelatie; 
	private byte sortSpellBook;
	private boolean showCombatSpells; 
	private boolean showSkillSpells; 
	private boolean showMiscallaneousSpells; 
	private boolean showTeleportSpells; 
	private byte spellBook;
	private byte autoCastSpell;
	
	public int getSpellId() {
		Integer tempCastSpell = (Integer) player.getTemporaryAttributtes().get("tempCastSpell");
		if(tempCastSpell != null)
			return tempCastSpell + 256;
		return autoCastSpell;
	}
	
	public int getAutoCastSpell() {
		return autoCastSpell;
	}
	
	public void resetSpells(boolean removeAutoSpell) {
		resetSpells(removeAutoSpell, false);
	}
	
	public void resetSpells(boolean removeAutoSpell, boolean reset) {
		player.getTemporaryAttributtes().remove("tempCastSpell");
		if(removeAutoSpell) {
			setAutoCastSpell(0, reset);
			refreshAutoCastSpell();
		}
	}
	public void setAutoCastSpell(int id) {
		setAutoCastSpell(id, false);
	}
	
	public void setAutoCastSpell(int id, boolean reset) {
		if(!reset)
			player.getPackets().sendGameMessage("Autocast spell "+(id == 0 ? "cleared" : "setted")+".", true);
		autoCastSpell = (byte) id;
		refreshAutoCastSpell();
	}
	
	public void refreshAutoCastSpell() {
		player.getPackets().sendConfig(108, getSpellAutoCastConfigValue());
	}
	
	public int getSpellAutoCastConfigValue() {
		switch(spellBook) {
		case 0:
			switch(autoCastSpell) {
			case 25: return 3;
			case 28: return 5;
			case 30: return 7;
			case 32: return 9;
			case 34: return 11; //air bolt
			case 39: return 13;//water bolt
			case 42: return 15;//earth bolt
			case 45: return 17; //fire bolt
			case 49: return 19;//air blast
			case 52: return 21;//water blast
			case 58: return 23;//earth blast
			case 63: return 25;//fire blast
			case 70: return 27;//air wave
			case 73: return 29;//water wave
			case 77: return 31;//earth wave
			case 80: return 33;//fire wave
			default: return 0;
			}
		default:
			return 0;
		}
		
	}
	
	public CombatDefinitions() {
		specialAttackPercentage = 100;
		autoRelatie = true;
		showCombatSpells = true;
		showSkillSpells = true;
		showMiscallaneousSpells = true;
		showTeleportSpells = true;
	}
	
	public void setSpellBook(int id) {
		spellBook = (byte) id;
		player.getInterfaceManager().sendMagicBook();
	}
	
	public int getSpellBook() {
		if(spellBook == 0)
			return 192; //normal
		else if (spellBook == 1)
			return 193; //ancients
		else
			return 430; //lunar
	}
	
	public void switchShowCombatSpells() {
		showCombatSpells = !showCombatSpells;
		refreshSpellBook();
	}
	
	public void switchShowSkillSpells() {
		showSkillSpells = !showSkillSpells;
		refreshSpellBook();
	}
	
	public void switchShowMiscallaneousSpells() {
		showMiscallaneousSpells = !showMiscallaneousSpells;
		refreshSpellBook();
	}
	
	public void switchShowTeleportSkillSpells() {
		showTeleportSpells = !showTeleportSpells;
		refreshSpellBook();
	}
	
	
	public void setSortSpellBook(int sortId) {
		this.sortSpellBook = (byte) sortId;
		refreshSpellBook();
	}
	public void refreshSpellBook() {
		player.getPackets().sendConfig(1376, sortSpellBook
				+ (showCombatSpells ? 0 : 512)
				+ (showSkillSpells ? 0 : 1024)
				+ (showMiscallaneousSpells ? 0 : 2048)
				+ (showTeleportSpells ? 0 : 4096));
	}
	
	public static final int getMeleeDefenceBonus(int bonusId) {
		if(bonusId == STAB_ATTACK)
			return STAB_DEF;
		if(bonusId == SLASH_DEF)
			return SLASH_DEF;
		return CRUSH_DEF;
	}
	public static final int getMeleeBonusStyle(int weaponId, int attackStyle) {
		switch(weaponId) {
		default:
			return CRUSH_ATTACK;
		}
	}
	
	public static final int getXpStyle(int weaponId, int attackStyle) {
		//TODO SHARED
		if(weaponId != -1) {
			String weaponName = ItemDefinitions.getItemDefinitions(weaponId).getName().toLowerCase();
			if(weaponName.contains("whip")) {
				switch(attackStyle) {
				case 0: return Skills.ATTACK;
				case 1: return SHARED;
				case 2:default: return Skills.DEFENCE;
				}
			}
			if(weaponName.contains("halberd")) {
				switch(attackStyle) {
				case 0: return SHARED;
				case 1: return Skills.STRENGTH;
				case 2:default: return Skills.DEFENCE;
				}
			}
			if(weaponName.contains("staff")) {
				switch(attackStyle) {
				case 0: return Skills.ATTACK;
				case 1: return Skills.STRENGTH;
				case 2:default: return Skills.DEFENCE;
				}
			}
			if(weaponName.contains("godsword")
					|| weaponName.contains("sword")
					|| weaponName.contains("2h")) {
				switch(attackStyle) {
				case 0: return Skills.ATTACK;
				case 1: return Skills.STRENGTH;
				case 2: return Skills.STRENGTH;
				case 3:default: return Skills.DEFENCE;
				}
			}
		}
		switch(weaponId) {
		case -1:
			switch(attackStyle) {
			case 0: return Skills.ATTACK;
			case 1: return Skills.STRENGTH;
			case 2:default: return Skills.DEFENCE;
			}
		default:
			switch(attackStyle) {
			case 0: return Skills.ATTACK;
			case 1: return Skills.STRENGTH;
			case 2: return SHARED;
			case 3:default: return Skills.DEFENCE;
			}
		}
	}
	
	public void setPlayer(Player player) {
		this.player = player;
		bonuses = new int[18];
	}
	
	public int[] getBonuses() {
		return bonuses;
	}
	public void refreshBonuses() {
		bonuses = new int[18];
		for(Item item : player.getEquipment().getItems().getItems()) {
			if(item == null)
				continue;
			int[] bonuses = ItemBonuses.getItemBonuses(item.getId());
			if(bonuses == null)
				continue;
			for(int id = 0; id < bonuses.length; id++) {
				if(id == 15 && this.bonuses[id] != 0) //means already has ranged bonus from something that isnt ammo
					continue;
				this.bonuses[id] += bonuses[id];
			}
		}
	}
	
	
	public void resetSpecialAttack() {
		desecreaseSpecialAttack(0);
		specialAttackPercentage = 100;
		refreshSpecialAttackPercentage();
	}
	
	public void restoreSpecialAttack() {
		if(specialAttackPercentage >= 100 || player.getInterfaceManager().containsScreenInter())
			return;
		specialAttackPercentage += specialAttackPercentage > 90 ? 100-specialAttackPercentage : 10;
		refreshSpecialAttackPercentage();
	}
	public void init() {
		refreshUsingSpecialAttack();
		refreshSpecialAttackPercentage();
		refreshAutoRelatie();
		sendUnlockAttackStylesButtons();
		refreshAttackStyle();
		refreshSpellBook();
		refreshAutoCastSpell();
	}
	
	public void checkAttackStyle() {
		setAttackStyle(attackStyle);
	}
	
	public void setAttackStyle(int style) {
		int maxSize = 3;
		int weaponId = player.getEquipment().getWeaponId();
		String name = weaponId == -1 ? "" : ItemDefinitions.getItemDefinitions(weaponId).getName().toLowerCase();
		if(weaponId == -1 || Combat.isRanging(player) != 0 
				|| name.contains("whip")
				|| name.contains("halberd"))
			maxSize = 2;
		if(style > maxSize)
			style = maxSize;
		if(style != attackStyle) {
			attackStyle = (byte) style;
			refreshAttackStyle();
		}
	}

	public void refreshAttackStyle() {
		player.getPackets().sendConfig(43, attackStyle);
	}
	
	public void sendUnlockAttackStylesButtons() {
		for(int componentId = 11; componentId <= 14; componentId++)
			player.getPackets().sendUnlockIComponentOptionSlots(884, componentId, -1, 0, 0);
	}
	public void switchUsingSpecialAttack() {
		usingSpecialAttack = !usingSpecialAttack;
		refreshUsingSpecialAttack();
	}
	
	public void desecreaseSpecialAttack(int ammount) {
		usingSpecialAttack = false;
		refreshUsingSpecialAttack();
		if(ammount > 0) {
			specialAttackPercentage -= ammount;
			refreshSpecialAttackPercentage();
		}
	}
	
	public int getSpecialAttackPercentage() {
		return specialAttackPercentage;
	}
	public void refreshUsingSpecialAttack() {
		player.getPackets().sendConfig(301, usingSpecialAttack ? 1 : 0);
	}
	
	public void refreshSpecialAttackPercentage() {
		player.getPackets().sendConfig(300, specialAttackPercentage*10);
	}
	
	
	public void switchAutoRelatie() {
		autoRelatie = !autoRelatie;
		refreshAutoRelatie();
	}
	public void refreshAutoRelatie() {
		player.getPackets().sendConfig(172, autoRelatie ? 0 : 1);
	}
	
	public boolean isUsingSpecialAttack() {
		return usingSpecialAttack;
	}
	
	public int getAttackStyle() {
		return attackStyle;
	}
	public boolean isAutoRelatie() {
		return autoRelatie;
	}
	public void setAutoRelatie(boolean autoRelatie) {
		this.autoRelatie = autoRelatie;
	}
}
